﻿using System;
using System.Collections.Generic;

namespace AutoCommunication.Helper
{
    /// <summary>
    /// 请求结果
    /// </summary>
    public class Result
    {
        /// <summary>
        ///
        /// </summary>
        public Result()
        {
        }

        /// <summary>
        /// 是否成功
        /// </summary>
        public bool IsSucceed { get; set; } = true;

        private string _Err;

        /// <summary>
        /// 异常消息
        /// </summary>
        public string Err
        {
            get
            {
                return _Err;
            }
            set
            {
                _Err = value;
                AddErr2List();
            }
        }

        /// <summary>
        /// 添加异常到异常集合
        /// </summary>
        public void AddErr2List()
        {
            if (!ErrList.Contains(Err))
                ErrList.Add(Err);
        }

        /// <summary>
        /// 异常Code
        /// 408 连接失败
        /// </summary>
        public int ErrCode { get; set; }

        private Exception exception;

        /// <summary>
        /// 详细异常
        /// </summary>
        public Exception Exception
        {
            get
            {
                return exception;
            }
            set
            {
                exception = value;
                AddException();
            }
        }

        private void AddException()
        {
            this.IsSucceed = false;
            Err = exception.Message;
        }

        /// <summary>
        /// 异常集合
        /// </summary>
        public List<string> ErrList { get; private set; } = new List<string>();

        /// <summary>
        /// 请求报文
        /// </summary>
        public string Requst { get; set; }

        /// <summary>
        /// 响应报文
        /// </summary>
        public string Response { get; set; }

        /// <summary>
        /// 返回的真实数据:用于解析
        /// </summary>
        public byte[] ResponseData { get; set; }

        /// <summary>
        /// 请求报文2
        /// </summary>
        public string Requst2 { get; set; }

        /// <summary>
        /// 响应报文2
        /// </summary>
        public string Response2 { get; set; }

        /// <summary>
        /// 耗时（毫秒）
        /// </summary>
        public double? TimeConsuming { get; private set; }

        /// <summary>
        /// 结束时间统计
        /// </summary>
        internal Result EndTime()
        {
            TimeConsuming = (DateTime.Now - InitialTime).TotalMilliseconds;
            return this;
        }

        /// <summary>
        /// 开始时间
        /// </summary>
        public DateTime InitialTime { get; protected set; } = DateTime.Now;

        /// <summary>
        /// 复制添加另外一个结果的IsSucceed/Err/code/Exception给自己
        /// </summary>
        /// <param name="result"></param>
        /// <returns></returns>
        public Result SetErrInfo(Result result)
        {
            IsSucceed = result.IsSucceed & IsSucceed;
            if (result.Err != null)
            {
                Err = result.Err;
            }
            ErrCode = result.ErrCode;
            if (result.Exception != null)
            {
                Exception = result.Exception;
            }

            foreach (var err in result.ErrList)
            {
                if (!ErrList.Contains(err))
                    ErrList.Add(err);
            }
            return this;
        }

        /// <summary>
        /// 前面的为True后,才继续进行后面的
        /// </summary>
        /// <param name="result"></param>
        /// <returns></returns>
        public Result Continue(Result result)
        {
            //todo 还处于测试阶段
            if (IsSucceed)
            {
                IsSucceed = result.IsSucceed & IsSucceed;
                if (result.Err != null)
                {
                    Err = result.Err;//必须要进行后面的循环,不然拿到的只是最后一次赋值的结果
                }
                ErrCode = result.ErrCode;
                Exception = result.Exception;
                foreach (var err in result.ErrList)
                {
                    if (!ErrList.Contains(err))
                        ErrList.Add(err);
                }
                return this;
            }
            else
            {
                return this;
            }
        }
    }

    /// <summary>
    /// 请求结果
    /// </summary>
    public class Result<T> : Result
    {
        /// <summary>
        ///
        /// </summary>
        public Result()
        {
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="data"></param>
        public Result(T data)
        {
            Value = data;
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="result"></param>
        public Result(Result result)
        {
            Assignment(result);
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="result"></param>
        /// <param name="data"></param>
        public Result(Result result, T data)
        {
            Assignment(result);
            Value = data;
        }

        /// <summary>
        /// 数据结果
        /// </summary>
        public T Value { get; set; }

        /// <summary>
        /// 结束时间统计
        /// </summary>
        public new Result<T> EndTime()
        {
            base.EndTime();
            return this;
        }

        /// <summary>
        /// 赋值
        /// </summary>
        private void Assignment(Result result)
        {
            IsSucceed = result.IsSucceed;
            InitialTime = result.InitialTime;
            Err = result.Err;
            Requst = result.Requst;
            Response = result.Response;
            Exception = result.Exception;
            ErrCode = result.ErrCode;
            base.EndTime();
            foreach (var err in result.ErrList)
            {
                if (!ErrList.Contains(err))
                    ErrList.Add(err);
            }
        }

        /// <summary>
        /// 设置异常信息和Succeed状态
        /// </summary>
        /// <param name="result"></param>
        /// <returns></returns>
        public new Result<T> SetErrInfo(Result result)
        {
            base.SetErrInfo(result);
            return this;
        }
    }
}